<template>
  <div class="mb-info" v-loading="loading">
    <div class="app-portal-cnt-hd">
      <div class="app-portal-hd-icon">
        <JIcon
          v-if="app.group_id === -100"
          :icon="DFT_ICONS.platform"
        />
        <JIcon
          v-else-if="app.group_id === -1"
          :icon="DFT_ICONS.global"
        />
        <JIcon
          v-else="app"
          :icon="DFT_ICONS.app"
        />
      </div>
      <div class="app-portal-title" v-html="app.group_name"></div>
      <div class="app-portal-tools">
      </div>
      <el-button
        v-if="canEdit(app)"
        class="app-group-add-btn"
        type="text"
        size="small"
        @click="showCustomCreateWin()">
        <JIcon :icon="DFT_ICONS.add" /> 注册组件
      </el-button>
    </div>
    <div class="flex-1 h-full overflow-y-auto page-card-container">
      <div
        v-for="comp in comps"
        :key="comp.id"
        style="height: auto;"
        v-resp="{ type: 'c24', container: 'parent', xlc: 4, lgc: 6, mdc: 6, smc: 8, xsc: 12 }"
        class="page-card"
        v-tippy="{ arrow: true }"
        :content="comp.remark || comp.comp_name"
      >
        <PageThumb
          :img="comp?.thumb"
          ratio-height="70%"
          mode="comp"
        >
          <div
            class="page-app"
            v-text="comp.comp_lib"
            v-copy="comp.comp_lib"
            v-tippy="{ arrow: true, placement : 'left' }"
            content="点击复制"
          />
          <div
            class="page-code"
            v-text="comp.comp_name"
            v-copy="comp.comp_name"
            v-tippy="{ arrow: true, placement : 'left' }"
            content="点击复制"
          />
          <JIcon
            :icon="DFT_ICONS.eye"
            class="page-card-action preview"
            v-tippy="{ arrow: true, placement : 'left' }"
            content="预览"
            @click="handleView(comp)"
          />
          <JIcon
            :icon="DFT_ICONS.edit"
            class="page-card-action"
            v-tippy="{ arrow: true, placement : 'left' }" content="修改"
            @click="handleShowCustomEditWin(comp)"
          />
          <JIcon
            :icon="comp.coverGeneing ? DFT_ICONS.loadingSpinner: DFT_ICONS.camera"
            class="page-card-action lowcode"
            v-tippy="{ arrow: true, placement : 'left' }"
            content="生成封面"
            @click="handleGeneCover(comp)"
          />
          <JIcon
            :icon="DFT_ICONS.delete"
            class="page-card-action delete"
            v-tippy="{ arrow: true, placement : 'left' }"
            content="删除"
            @click="handleDelete(comp)"
          />
        </PageThumb>
        <div class="page-info">
          <JIcon v-if="isCompTypeH5(comp)" :icon="DFT_ICONS.h5" />
          <JIcon v-if="isCompTypePc(comp)" :icon="DFT_ICONS.pc" />
          <JIcon v-if="isCompTypeBs(comp)" :icon="DFT_ICONS.big" />
          <div class="page-title" v-text="comp.name" />
        </div>
      </div>
    </div>

    <el-pagination
      @size-change="refresh"
      @current-change="refresh"
      v-model:current-page="pagination.page"
      v-model:page-size.sync="pagination.pageSize"
      :page-sizes="[10, 20, 50, 100]"
      layout="total, sizes, prev, pager, next"
      :total="pagination.total"
      class="p-2"
    />

    <el-dialog
      v-if="currentPage"
      :title="'预览组件：' + currentPage.name"
      width="80%"
      style="height:85%;top:7%;"
      v-model="pagePreviewShow"
      custom-class="m-dialog-fullscreen"
      :close-on-click-modal="true"
      :append-to-body="true"
    >
      <iframe
        class="w-full h-full"
        style="border: 1px solid #EEE;"
        frameborder="0"
        :src="`/apps/jwpage/?app=_nh#/compage?_lib=${currentPage.comp_lib}&_comp=${ currentPage.comp_name }`"
      />
    </el-dialog>

    <el-dialog
      title="创建组件"
      v-model="createShow"
      custom-class="m-dialog-fullscreen"
      :close-on-click-modal="false"
      :append-to-body="true"
      :fullscreen="true"
    >
      <div class="comps-form-wrap">
        <div class="comps-form">
          <div class="code-wrap">
            <!--<div style="margin-bottom: 10px;">组件描述文件：</div>-->
            <CodeEditor v-model="createForm.comp_def" @blur="compDefToProp"></CodeEditor>
          </div>
          <div class="form-props">
            <el-form
              :model="createForm"
              ref="createFormRef"
              :rules="rules"
              class="form mp-form"
              label-width="100px"
              size="small">
              <el-form-item label="组件名称" prop="name">
                <el-input v-model="createForm.name" autocomplete="off" :disabled="isView || isEdit"
                          @blur="propToCompDef" placeholder="组件中文名"></el-input>
              </el-form-item>
              <el-form-item label="组件名" prop="comp_name">
                <el-input v-model="createForm.comp_name" autocomplete="off" :disabled="isView"
                          @blur="propToCompDef" placeholder="组件名，如: JdclibTask"></el-input>
              </el-form-item>
              <el-form-item label="库名" prop="comp_lib">
                <el-input v-model="createForm.comp_lib" autocomplete="off" :disabled="isView"
                          @blur="propToCompDef" placeholder="组件库名，如: jdclib"></el-input>
              </el-form-item>
              <!--<el-form-item label="组件图标" prop="icon">
                  <icon-picker v-model="createForm.icon"></icon-picker>
              </el-form-item>-->
              <el-form-item label="组件支持类型" prop="stypes">
                <el-checkbox-group v-model="createForm.stypes" size="mini">
                  <el-checkbox-button :label="2">
                    <i class="fa fa-mobile-alt" style="font-size:12px;margin-right:5px;"></i> H5
                  </el-checkbox-button>
                  <el-checkbox-button :label="5">
                    <i class="fa fa-laptop" style="font-size:12px;margin-right:5px;"></i> Web页
                  </el-checkbox-button>
                  <el-checkbox-button :label="1">
                    <i class="fa fa-tv" style="font-size:12px;margin-right:5px;"></i> 大屏
                  </el-checkbox-button>
                </el-checkbox-group>
              </el-form-item>
              <el-form-item label="标签" prop="tags">
                <el-tag :key="tag"
                        v-for="tag in createForm.tags"
                        closable
                        :disable-transitions="false"
                        @close="handleTagClose(tag)">
                  {{ tag }}
                </el-tag>
                <div>
                  <el-input
                    class="input-new-tag"
                    v-if="tagVisible"
                    v-model="tagValue"
                    v-focus
                    ref="saveTagInputRef"
                    size="small"
                    @keyup.enter.native="handleTagConfirm"
                    @blur="handleTagConfirm">
                  </el-input>
                  <template v-else>
                    <el-button class="button-new-tag" size="mini" @click="showTagInput">+ 标签</el-button>
                    <el-popover placement="right">
                      <el-tag v-for="tag in commonTags"
                              @click="handleTagSelect(tag)">
                        {{ tag }}
                      </el-tag>
                      <el-button slot="reference" class="button-new-tag" size="mini">+ 常用</el-button>
                    </el-popover>
                  </template>
                </div>
              </el-form-item>
              <el-form-item label="组件预览图" prop="thumb">
                <file-picker v-model="createForm.thumb" :accept-type="3" :height="60"></file-picker>
              </el-form-item>
              <el-form-item label="组件地址" prop="comp_url">
                <el-input v-model="createForm.comp_url" autocomplete="off" :disabled="isView"></el-input>
              </el-form-item>
              <el-form-item label="组件描述" prop="remark">
                <el-input v-model="createForm.remark" type="textarea" :rows="2" autocomplete="off"
                          :disabled="isView"></el-input>
              </el-form-item>

              <el-form-item v-if="isView">
                <el-button type="primary" @click="handleCustomCloseWin()">确 定</el-button>
              </el-form-item>
            </el-form>
            <div class="btns">
              <el-button type="primary" @click="handleSave()">确 定</el-button>
              <el-button @click="handleCustomCloseWin()">取 消</el-button>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import {ref, reactive, computed, watch, onMounted} from 'vue';
import _ from 'lodash';
import {useCommonStore} from "@jzl/stores";
import {api} from "@jzl/api";
import {$utils} from "@jzl/utils";
import {DFT_ICONS} from "@jzl/icons";

const DFT_FORM = {
  cate: 3,
  page_code: '',
  page_name: '',
  page_desc: '',
  url: '',
  stypes: [1, 2, 5],
  tags: [],
  comp_def: `{
    "component": "",
    "icon": "",
    "name": "",
    "lib": "",
    "ele_style": {
        "_name": "元素名称",
        "_node": "div",
        "_common_style": {
            "display": "block",
            "justify-content": "center",
            "marginType": "set",
            "marginTop": "0px",
            "marginRight": "0px",
            "marginBottom": "0px",
            "marginLeft": "0px"
        }
    },
    "data_fieldsmap": {},
    "data_schema": {},
    "data_format": "",
    "data_type": "static",
    "data_dync": {},
    "data_static": {}
}`
};

const props = defineProps({
  appId: [Number, String],
  lib: {
    type: String,
    default: ""
  },
  tag: {
    type: String,
    default: ""
  },
});

const selected = ref(null);
const modId = ref(null);
const formLabelWidth = ref('160px');
const winName = ref('新增');
const createFormRef = ref();

const app = reactive({
  group_id: -100,
  group_name: '平台通用组件'
});
const comps = ref([]);
const loading = ref(false);
const pagination = reactive({
  page: 1,
  pageSize: 50,
  total: 0
});

const form = reactive({
  name: ''
});

const queryUuid = ref("");
const pagePreviewShow = ref(false);
const currentPage = ref({});
const isView = ref(false);

const createForm = ref(_.clone(DFT_FORM));
const createShow = ref(false);
const tagVisible = ref(false);
const tagValue = ref('');
const commonTags = ref(['box', 'tabs', 'feature']);

const loginUser = computed(() => useCommonStore().loginUser);

const queryCate = computed(() => {
  let cate = -1;
  let groupId = _.get(app, "group_id");

  if (app) {
    if (groupId === -200) {
      cate = -1;
    } else if (groupId === -100) {
      cate = 1;
    } else if (groupId === -1) {
      cate = 2;
    } else {
      cate = 3;
    }
  } else {
    cate = -1;
  }

  return cate;
});

watch(() => props.appId, (val) => {
  changeApp();
});

watch(() => props.tag, () => {
  refresh();
});

watch(() => props.lib, () => {
  refresh();
});

onMounted(() => {
  init();
  refresh();
});

const isCompTypeH5 = (comp) => {
  let stypes = _.get(comp, "stypes");
  return _.indexOf(stypes, 2) >= 0;
};

const isCompTypePc = (comp) => {
  let stypes = _.get(comp, "stypes");
  return _.indexOf(stypes, 5) >= 0;
};

const isCompTypeBs = (comp) => {
  let stypes = _.get(comp, "stypes");
  return _.indexOf(stypes, 1) >= 0;
};

const canEdit = (data) => {
  let gid = _.get(data, "group_id");
  let isSuper = _.get(loginUser.value, 'type') === 'SUPER';
  let isSSuper = _.get(loginUser.value, 'type') === '_SUPER';

  if (isSSuper) return true;

  if (gid >= -1 && isSuper) {
    return true;
  }

  return false;
};

const init = async () => {
  selected.value = null;
};

const refresh = $utils.buffer(async () => {
  let query = _.cloneDeep(form);
  let app_id = -1;
  let cate = queryCate.value;

  queryUuid.value = $utils.getNanoid(8);
  loading.value = true;

  if (cate === 3) {
    app_id = _.get(app, 'group_id');
  }

  query.app_id = app_id;
  query.cate = cate;
  query.comp_lib = props.lib;
  query.tag = props.tag;

  let ret = await api.comp.getCompList(query, pagination);
  comps.value = _.get(ret, 'rows', []);
  pagination.total = _.get(ret, 'count', 0);

  loading.value = false;
}, 50);

const changeApp = async () => {
  let appData = {};
  if (props.appId === -200) {
    appData = {
      group_id: -200,
      group_name: '全部'
    };
  } else if (props.appId === -100) {
    appData = {
      group_id: -100,
      group_name: '平台通用组件'
    };
  } else if (props.appId === -1) {
    appData = {
      group_id: -1,
      group_name: '系统通用组件'
    };
  } else if (props.appId > 0) {
    appData = await api.group.getGroup(props.appId);
  }

  Object.assign(app, appData);

  refresh();
};

const handleView = (page) => {
  pagePreviewShow.value = true;
  currentPage.value = page;
};

const showCustomCreateWin = () => {
  createShow.value = true;
  winName.value = '注册组件';
  currentPage.value = null;
  createFormRef.value?.resetFields();

  let appId = _.get(app, 'group_id') || -1;
  if (appId <= 0) appId = -1;

  let cate = queryCate.value;
  if (cate < 0) {
    if (appId > 0) {
      cate = 3;
    } else {
      cate = 1;
    }
  }

  createForm.value = _.defaults({
    page_code: $utils.getNanoid(),
    app_id: appId,
    cate
  }, DFT_FORM);
};

const handleCustomCloseWin = (flag) => {
  createShow.value = false;
  refresh();
};

const handleShowCustomEditWin = async (page) => {
  let createFormData = _.cloneDeep(page);
  let compDefNew = JSON.stringify(page.comp_def, null, 4);

  createFormData.comp_def = compDefNew;
  if (!createFormData.stypes) createFormData.stypes = [];

  createForm.value = createFormData;
  createShow.value = true;
};

const str2json = (jsonStr) => {
  return eval(`(${jsonStr})`);
};

const handleSave = async () => {
  let ret = null;
  let createFormData = _.cloneDeep(createForm.value);

  if (_.isString(createFormData.comp_def)) {
    let json = str2json(createFormData.comp_def);

    createFormData.comp_def = json;
  }

  if (createFormData.id) {
    ret = await api.comp.updateComp(createFormData);
  } else {
    ret = await api.comp.createComp(createFormData);
  }

  if (ret) {
    this.$message('操作成功！');
    refresh();
    createShow.value = false;
  }
};

const _delete = async (id) => {
  let ret = await api.comp.removeComp(id);

  if (ret) {
    refresh();
  }
};

const handleDelete = (it) => {
  if (!it || !it.id) return;

  this.$confirm(`此操作将永久删除该组件【${it.name}】, 是否继续?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    await _delete(it.id);
  }).catch(() => {
  });
};

const propToCompDef = () => {
  let compDefStr = createForm.value.comp_def;

  if (compDefStr) {
    try {
      let compDefJson = str2json(compDefStr);

      if (compDefJson) {
        if (createForm.value.comp_name) {
          compDefJson.component = createForm.value.comp_name;
        }

        if (createForm.value.name) {
          compDefJson.name = createForm.value.name;
        }

        if (createForm.value.icon) {
          compDefJson.icon = createForm.value.icon;
        }

        if (createForm.value.comp_lib) {
          compDefJson.lib = createForm.value.comp_lib;
        }

        let compDefNew = JSON.stringify(compDefJson, null, 4);

        createForm.value.comp_def = compDefNew;
      }
    } catch (e) {
    }
  }
};

const compDefToProp = () => {
  if (createForm.value.comp_def) {
    try {
      let json = str2json(createForm.value.comp_def);
      let component = _.get(json, "component");
      let name = _.get(json, "name");
      let lib = _.get(json, "lib");

      if (!createForm.value.comp_name) {
        createForm.value.comp_name = component;
      }

      if (!createForm.value.name) {
        createForm.value.name = name;
      }

      if (!createForm.value.comp_lib) {
        createForm.value.comp_lib = lib;
      }
    } catch (e) {
      this.$jui.toast("JSON 格式有问题！");
    }
  }
};

const handleGeneCover = async (comp) => {
  if (!comp || !comp.id) return;

  comp.coverGeneing = true;
  try {
    await this.$putils.geneCompScreenshot(comp);
  } catch (e) {
  }

  // this.$set(comp, "coverGeneing", false);
  comp.coverGeneing = false;

  let newComp = await api.comp.getComp(comp.id);
  _.assignIn(comp, newComp);
};

const handleTagClose = (tag) => {
  createForm.value.tags.splice(createForm.value.tags.indexOf(tag), 1);
};

const showTagInput = () => {
  tagVisible.value = true;
};

const handleTagSelect = (tag) => {
  if (tag) {
    if (!createForm.value.tags) createForm.value.tags = [];
    if (_.indexOf(createForm.value.tags, tag) < 0) {
      createForm.value.tags.push(tag);
    }
  }
};

const handleTagConfirm = () => {
  let inputValue = tagValue.value;
  if (inputValue) {
    if (!createForm.value.tags) createForm.value.tags = [];
    createForm.value.tags.push(inputValue);
  }
  tagVisible.value = false;
  tagValue.value = '';
};
</script>


<style lang="scss" scoped>
.page-card {
  /*width: 296px;*/
  /*height: 210px;*/

  .page-cover {
    height: 180px;
  }

  .page-info {
    > i {
      font-size: 12px;
      color: #409eff;
      transform: scale(0.85);
    }
  }
}

.comps-form-wrap {
  display: flex;
  flex-flow: column;
  height: 100%;
  overflow: auto;

  .comps-form {
    flex: 1;
    height: 100%;
    display: flex;
    align-items: stretch;

    .form-props {
      width: 500px;
      padding: 80px 50px;
    }

    .code-wrap {
      flex: 1;
      overflow: auto;

      .vue-codemirror {
        height: 100%;
      }
    }
  }

  .btns {
    text-align: center;
    padding: 10px;
  }
}

.el-tag + .el-tag {
  margin-left: 10px;
}

.button-new-tag {
  margin-right: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}

.input-new-tag {
  width: 120px;
  vertical-align: bottom;
}
</style>
